package com.ruoyi.wb.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.ruoyi.common.config.XlsConfig;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.GlobalException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.mapper.SysRoleMapper;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.wb.domain.*;
import com.ruoyi.wb.dto.*;
import com.ruoyi.wb.enmus.*;
import com.ruoyi.wb.mapper.*;
import com.ruoyi.wb.service.*;
import com.ruoyi.wb.utils.XlsCopyToPngUtil;
import com.ruoyi.wb.vo.*;
import org.apache.commons.lang3.StringUtils;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.YearMonth;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

import static com.ruoyi.common.utils.PageUtils.startPage;

/**
 * 维保计划Service业务层处理
 *
 * @author ruoyi
 * @date 2024-10-14
 */
@Service
public class WbPlanServiceImpl implements IWbPlanService {
    @Autowired
    private WbPlanMapper wbPlanMapper;

    @Autowired
    private SysRoleMapper roleMapper;

    @Autowired
    private WbPlanContentMapper wbPlanContentMapper;

    @Autowired
    private IWbPlanClassifyService iWbPlanClassifyService;

    @Autowired
    private WbClassifyMapper wbClassifyMapper;

    @Autowired
    private IWbPlanContentService iWbPlanContentService;

    @Autowired
    private IWbClassifyContentService iWbClassifyContentService;

    @Autowired
    private IWbEntAuthService iWbEntAuthService;

    @Autowired
    private IWbContractService iWbContractService;

    @Autowired
    private IWbMaintainCompanyService wbMaintainCompanyService;

    @Autowired
    private IWbInformService iWbInformService;

    @Autowired
    private WbClassifyYearServiceImpl wbClassifyYearService;

    @Autowired
    private IWbEntAuthService wbEntAuthService;

    @Autowired
    private IWbClassifyYearService iWbClassifyYearService;

    @Autowired
    private WbClassifyYearContentThreeServiceImpl wbClassifyYearContentThreeService;
    @Autowired
    private IWbContractService wbContractService;

    @Autowired
    private WbPlanClassifyYearContentServiceImpl wbPlanClassifyYearContentService;

    @Autowired
    private WbPlanClassifyYearContentThreeServiceImpl wbPlanClassifyYearContentThreeService;
    @Autowired
    private IWbMaintainCompanyService iWbMaintainCompanyService;
    @Autowired
    private WbPlanClassifyMapper wbPlanClassifyMapper;

    @Autowired
    private IWbMaintainCompanyUserService wbMaintainCompanyUserService;

    @Autowired
    private SqlSessionTemplate sqlSessionTemplate;

    @Autowired
    private IWbPlanClassifyYearService wbPlanClassifyYearService;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private WbInformMapper wbInformMapper;


    private static final ExecutorService exec = Executors.newCachedThreadPool();

    /**
     * 查询维保计划
     *
     * @pram id 维保计划主键
     * @return 维保计划
     */
    @Override
    public WbPlan selectWbPlanById(Long id) {
        return wbPlanMapper.selectWbPlanById(id);
    }

    /**
     * 查询维保计划列表
     *
     * @param wbPlan 维保计划
     * @return 维保计划
     */
    @Override
    public List<WbPlan> selectWbPlanList(WbPlan wbPlan) {
        List<WbPlan> wbPlans = new ArrayList<>();
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser user = loginUser.getUser();
        Long userId = user.getUserId();
        List<SysRole> roles = user.getRoles();
        //超级管理员  平台管理员  消防单位 全返回
        if (userId.toString().equals(RoleNameEnums.ADMIN.getType().toString())) {
            startPage();
            wbPlans = wbPlanMapper.selectWbPlanList(wbPlan);
        }
        for (SysRole role : roles) {
            if (role.getRoleId().toString().equals(RoleNameEnums.PTGLY.getType().toString())||
                    role.getRoleId().toString().equals(RoleNameEnums.FIRE_UNIT_MANAGER.getType().toString())||
                    role.getRoleId().toString().equals(RoleNameEnums.FIREFIGHTER.getType().toString())
            ) {
                startPage();
                wbPlans = wbPlanMapper.selectWbPlanList(wbPlan);
            }
        }
        //只能看自己维保公司的
        List<WbMaintainCompany> wbMaintainCompanies = iWbMaintainCompanyService.selectWbMaintainCompanyByUserId(userId);
        if (!CollectionUtils.isEmpty(wbMaintainCompanies)) {
            wbPlan.setWbCompanyId(wbMaintainCompanies.get(0).getId());
            startPage();
            wbPlans = wbPlanMapper.selectWbPlanList(wbPlan);
        }


        return wbPlans;
    }

    /**
     * 新增维保计划
     *
     * @param wbPlan 维保计划
     * @return 结果
     */
    @Override
    public int insertWbPlan(WbPlan wbPlan) {
        wbPlan.setCreateTime(DateUtils.getNowDate());
        return wbPlanMapper.insertWbPlan(wbPlan);
    }

    /**
     * 修改维保计划
     *
     * @param wbPlan 维保计划
     * @return 结果
     */
    @Override
    public int updateWbPlan(WbPlan wbPlan) {
        wbPlan.setUpdateTime(DateUtils.getNowDate());
        if (!ObjectUtils.isEmpty(wbPlan.getExecStatus()) && wbPlan.getExecStatus().equals(PlanExecuteStatusEnums.COMPLETED.getStatus())) {
            wbPlan.setFinishTime(DateUtils.getNowDate());
            wbPlan.setIfDownload(1L);
        }
        return wbPlanMapper.updateWbPlan(wbPlan);
    }

    /**
     * 批量删除维保计划
     *
     * @param ids 需要删除的维保计划主键
     * @return 结果
     */
    @Override
    public int deleteWbPlanByIds(Long[] ids) {
        return wbPlanMapper.deleteWbPlanByIds(ids);
    }

    /**
     * 删除维保计划信息
     *
     * @param id 维保计划主键
     * @return 结果
     */
    @Override
    public int deleteWbPlanById(Long id) {
        return wbPlanMapper.deleteWbPlanById(id);
    }

    /**
     * 查询当前登录用户维保信息
     *
     * @param wbPlan
     * @return
     */
    @Override
    public List<WbPlan> selectUserMaintainInfoPage(WbPlan wbPlan, Long userId) {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        List<SysRole> roles = user.getRoles();
        if (CollectionUtils.isEmpty(roles)) {
            throw new RuntimeException("该用户没有角色信息");
        }
        wbPlan.setOperaterId(userId);
        return wbPlanMapper.selectWbPlanListByRole(wbPlan);
    }

    /**
     * 上传任务表单信息查询
     *
     * @param planId
     * @return
     */
    @Override
    public WbContractVo getJobInfoByPlanId(Long planId) {
        return wbPlanMapper.getJobInfoByPlanId(planId);
    }

    /**
     * 提交任务
     *
     * @param dtos
     * @return
     */
    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public boolean submitJob(List<WbPlanContentDto> dtos, Long userId) {
        for (WbPlanContentDto dto : dtos) {
            WbPlanContent wbPlan = new WbPlanContent();
            BeanUtils.copyProperties(dto, wbPlan);

            if (StringUtils.isNotBlank(dto.getResult())) {
                wbPlan.setResult(dto.getResult().equals("合格") ? 1L : 2L);
            }
            wbPlan.setUpdateTime(DateUtils.getNowDate());
            wbPlanContentMapper.updateWbPlanContent(wbPlan);
        }
        Long classifyId = dtos.stream().map(WbPlanContentDto::getClassifyId).collect(Collectors.toList()).get(0);
        WbPlanClassify classify = iWbPlanClassifyService.selectWbPlanClassifyById(classifyId);
        if (classify.getExecStatus() == 0) {
            classify.setUpdateTime(new Date());
            classify.setExecStatus(1L);
            iWbPlanClassifyService.updateWbPlanClassify(classify);

            Long planId = dtos.stream().map(WbPlanContentDto::getPlanId).collect(Collectors.toList()).get(0);
            WbPlan wbPlan = this.selectWbPlanById(planId);
            //  wbPlan.setExecutory(wbPlan.getExecutory() - 1);
            this.updateWbPlan(wbPlan);
        }
        return true;
    }

    /**
     * 我要年检
     *
     * @param userId
     * @return
     */
    @Override
    public List<WbPlan> examineJob(Long userId, String key, String type) {
        List<String> sysRole = getRole(userId);
        if (CollectionUtils.isEmpty(sysRole)) {
            return Collections.emptyList();
        } else if (!sysRole.contains(RoleNameEnums.MAINTAIN_STAFF.getDescribe())) {
            return Collections.emptyList();
        }
        return wbPlanMapper.examineJob(userId, key, type);
    }

    /**
     * 数据统计
     *
     * @return
     */
    @Override
    public WbPlanDataStatisticsVo dataStatistics(Long userId) {
        int monthCount = wbPlanMapper.getMonthCount(userId);
        int monthAccomplish = wbPlanMapper.getMonthAccomplish(userId);
        int todayMaintenanceJob = wbPlanMapper.getTodayMaintenanceJob(userId);
        int todayMaintainJob = wbPlanMapper.getTodayMaintainJob(userId);
        return WbPlanDataStatisticsVo.builder()
                .monthCount(monthCount)
                .monthAccomplish(monthAccomplish)
                .todayMaintenanceJob(todayMaintenanceJob)
                .todayMaintainJob(todayMaintainJob).build();
    }

    /**
     * 维保计划审核通过
     *
     * @param dto
     * @return
     */
    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public int planAudit(WbPlanAuditDto dto) {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        // 如果计划状态是已提交,代表是第一次审核通过,第一次审核通过状态改为审核中
        WbPlan temp = wbPlanMapper.selectWbPlanById(dto.getPlanId());
        if (!temp.getExecStatus().equals(dto.getStatus())) {
            throw new RuntimeException("该计划已被其他人操作请刷新页面");
        }
        WbPlan wbPlan = new WbPlan();
        wbPlan.setId(dto.getPlanId());
        if (dto.getStatus().equals(PlanExecuteStatusEnums.SUBMITTED.getStatus())) {
            wbPlan.setExecStatus(PlanExecuteStatusEnums.UNDER_REVIEW.getStatus());
            wbPlan.setAuditStatus(PlanAuditStatusEnums.UNDER_REVIEW.getStatus());
            // 如果是审核中状态代表是第二次审核通过改为已完成
        } else if (dto.getStatus().equals(PlanExecuteStatusEnums.UNDER_REVIEW.getStatus())) {
            wbPlan.setExecStatus(PlanExecuteStatusEnums.MAINTENANCE.getStatus());
            wbPlan.setAuditStatus(PlanAuditStatusEnums.AUDITED.getStatus());
            wbPlan.setExecEndTime(DateUtils.getNowDate());
            //使用单独线程完成
            exec.submit(() -> {
                try {
                    WbPlan tempWbPlan = wbPlanMapper.selectWbPlanById(dto.getPlanId());

                    //插入消息

                    WbInform wbInform = new WbInform();
                    wbInform.setClientId(tempWbPlan.getClientId());
                    wbInform.setClientName(tempWbPlan.getClientName());
                    wbInform.setInformType(WbInformType.EXAMINING_REPORT.getCode());
                    wbInform.setTitle("您有新的检测报告");
                    wbInform.setContent("您有新的检测报告：" +tempWbPlan.getPlanName()+
                            "需要下载");
                    wbInform.setCreateTime(DateUtils.getNowDate());
                    wbInform.setCreateBy(user.getUserId().toString());
                    wbInform.setUpdateTime(DateUtils.getNowDate());
                    wbInform.setUpdateBy(user.getUserId().toString());
                    wbInform.setIfRead(WbInformType.UNREAD.getCode());
                    wbInform.setDelFlag(WbInformType.EXIST.getCode());
                    wbInform.setRelevantBillsId(tempWbPlan.getId());
                    if (wbInformMapper.insertWbInform(wbInform)==0){
                        throw new RuntimeException("新增消息失败");
                    }


                    //查询用户签名
                    SysUser engineer = sysUserService.selectUserById(tempWbPlan.getEngineerId());
                    SysUser fireFighting = sysUserService.selectUserById(tempWbPlan.getFireFightingId());
                    SysUser operator = sysUserService.selectUserById(tempWbPlan.getOperaterId());
                    //查询维保公司信息
                    WbMaintainCompany wbMaintainCompany = wbMaintainCompanyService.selectWbMaintainCompanyById(tempWbPlan.getWbCompanyId());
                    //合同id
                    Long contractId = tempWbPlan.getContractId();
                    //维保合同
                    WbContract wbContract = wbContractService.selectWbContractById(contractId);
                    //业主单位
                    WbEntAuth wbEntAuth = wbEntAuthService.selectWbEntAuthById(tempWbPlan.getClientId());


                    tempWbPlan.setContractName(wbContract.getCode());

                    StringBuilder stringBuilder = new StringBuilder();
                    stringBuilder.append(StringUtils.isNotBlank(wbEntAuth.getProvinceString())?wbEntAuth.getProvinceString():"").append(StringUtils.isNotBlank(wbEntAuth.getProvinceString())?"/":"")
                    .append(StringUtils.isNotBlank(wbEntAuth.getCityString())?wbEntAuth.getCityString():"").append(StringUtils.isNotBlank(wbEntAuth.getCityString())?"/":"")
                    .append(StringUtils.isNotBlank(wbEntAuth.getCountyString())?wbEntAuth.getCountyString():"").append(StringUtils.isNotBlank(wbEntAuth.getCountyString())?"/":"")
                    .append(StringUtils.isNotBlank(wbEntAuth.getEntAddress())?wbEntAuth.getEntAddress():"");

                    tempWbPlan.setEngineerSignature(engineer.getSignature());
                    tempWbPlan.setEngineerPersonalSeal(engineer.getPersonalSeal());
                    tempWbPlan.setFiremenSignature(fireFighting.getSignature());
                    tempWbPlan.setFiremenPersonalSeal(fireFighting.getPersonalSeal());
                    tempWbPlan.setOperatorSignature(operator.getSignature());
                    tempWbPlan.setCommonLogo(wbMaintainCompany.getLogo());
                    tempWbPlan.setCommonSeal(wbMaintainCompany.getCommonSeal());
                    //地址
                    tempWbPlan.setClientAddress(stringBuilder.toString());
                    if (tempWbPlan.getPlanType().equals(PlanTypeEnums.MONTHLY.getType())) {
                        WbPlanClassifyDto wbPlanClassifyDto = new WbPlanClassifyDto();
                        wbPlanClassifyDto.setPlanId(dto.getPlanId());
                        List<WbPlanClassifyVo> list = iWbPlanClassifyService.getCatalogueItemByPlanId(wbPlanClassifyDto);
                        list = list.stream().filter(WbPlanClassifyVo::getIsCheckedStatus).collect(Collectors.toList());
                        String xlsName = XlsCopyToPngUtil.copyXlsMonth(list, tempWbPlan, true);
                        String pngName = XlsCopyToPngUtil.xlsToPng(xlsName, PlanTypeEnums.MONTHLY.getType());
                        String pdfName = XlsCopyToPngUtil.xlsToPdf(xlsName, PlanTypeEnums.MONTHLY.getType());
                        WbPlan wbPlan1 = new WbPlan();
                        wbPlan1.setId(dto.getPlanId());
                        wbPlan1.setExaminingReport(XlsConfig.MONTH_URL + pngName);
                        int i = wbPlanMapper.updateWbPlan(wbPlan1);
                        if (i == 0) {
                            throw new RuntimeException("维保计划月检图片插入失败");
                        }
                    } else if (tempWbPlan.getPlanType().equals(PlanTypeEnums.YEAR.getType())) {
                        List<WbPlanClassifyYearVo> list = wbPlanClassifyYearService.getCatalogueYearItemByPlanId(dto.getPlanId());
                        String xlsName = XlsCopyToPngUtil.copyXlsYear(list, tempWbPlan, true, wbEntAuth);
                        String pngName = XlsCopyToPngUtil.xlsToPng(xlsName, PlanTypeEnums.YEAR.getType());
                        String pdfName = XlsCopyToPngUtil.xlsToPdf(xlsName, PlanTypeEnums.YEAR.getType());

                        WbPlan wbPlan1 = new WbPlan();
                        wbPlan1.setId(dto.getPlanId());
                        wbPlan1.setExaminingReport(XlsConfig.YEAR_URL + pngName);
                        int i = wbPlanMapper.updateWbPlan(wbPlan1);
                        if (i == 0) {
                            throw new RuntimeException("维保计划年检图片插入失败");
                        }
                    }

                } catch (Exception e) {
                    System.err.println("id为" + dto.getPlanId() + " 的计划生成图片失败");
                    e.printStackTrace();
                }
            });


        }
        wbPlanMapper.updateWbPlan(wbPlan);
        // 新增日志记录
        dto.setStatus(1);
        return wbPlanMapper.savePlanAuditLog(dto);
    }

    /**
     * 维保计划驳回
     *
     * @param dto
     * @return
     */
    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public boolean reject(WbPlanAuditDto dto) {

        //查询是否已经驳回
        WbPlan item = wbPlanMapper.selectWbPlanById(dto.getPlanId());
        if (item.getExecStatus().equals(PlanExecuteStatusEnums.REJECT.getStatus())){
            throw new RuntimeException("该计划已被其他用户操作，请刷新页面。");
        }


        // 修改维保计划为驳回
        WbPlan wbPlan = new WbPlan();
        wbPlan.setId(dto.getPlanId());
        wbPlan.setExecStatus(PlanExecuteStatusEnums.REJECT.getStatus());
        wbPlan.setAuditStatus(PlanAuditStatusEnums.REJECT.getStatus());
        wbPlanMapper.updateWbPlan(wbPlan);
        // 新增日志记录
        dto.setStatus(0);
        wbPlanMapper.savePlanAuditLog(dto);
        // 逻辑删除掉之前的审核记录
        wbPlanMapper.deletePlanAuditLog(dto.getPlanId());
        return true;
    }

    /**
     * 批量选择任务为今日任务
     *
     * @param planIds
     * @return
     */
    @Override
    public boolean todayJob(List<Long> planIds) {
        wbPlanMapper.todayJob(planIds);
        return true;
    }

    /**
     * 今日维保
     *
     * @param userId
     * @return
     */
    @Override
    public List<WbPlan> todayPlan(Integer execStatus, Long userId) {
        return wbPlanMapper.todayPlan(execStatus, userId);
    }

    /**
     * 新增维保
     *
     * @param dto
     * @return
     */
    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public boolean savePlan(WbPlanDto dto) {
        chenDate(dto);
        WbPlan wbPlan = new WbPlan();
//        WbMaintainCompanyUserVo engineer = wbMaintainCompanyUserService.selectWbMaintainCompanyUserById(dto.getEngineerId());
//        WbMaintainCompanyUserVo firemen = wbMaintainCompanyUserService.selectWbMaintainCompanyUserById(dto.getFireFightingId());
//        dto.setEngineerSignature(engineer.getSignature());
//        dto.setFiremenSignature(firemen.getSignature());
        BeanUtils.copyProperties(dto, wbPlan);


        wbPlan.setCreateTime(DateUtils.getNowDate());
        if (dto.getPlanType().equals(PlanTypeEnums.MONTHLY.getType())) {
            // 目录
            int size = (int) dto.getClassifyList().stream().filter(f -> f.getIsCheckedStatus().equals(true)).count();
            wbPlan.setContentNum((long) size);
            wbPlan.setExecutory((long) size);

            //月检要批量

            if (CollectionUtils.isEmpty(dto.getSelectMonths())) {
                throw new RuntimeException("至少选择一个月");
            }
            extracted(dto);


        }
        if (dto.getPlanType().equals(PlanTypeEnums.YEAR.getType())) {
            //查询所有年计划 一级二级三级目录
            List<WbClassifyYearContentThree> wbClassifyYearContentThrees = wbClassifyYearContentThreeService.selectWbClassifyYearContentThreeList(new WbClassifyYearContentThree());
            wbPlan.setContentNum((long) wbClassifyYearContentThrees.size());
            wbPlan.setExecutory((long) wbClassifyYearContentThrees.size());
            wbPlan.setExecStatus(PlanExecuteStatusEnums.TO_BEGIN.getStatus());
            wbPlan.setPlanName(dto.getClientName()+DateUtils.parseDateToStr("yyyy",dto.getPlanStartDate())+"年度维保计划");
            wbPlanMapper.insertWbPlan(wbPlan);
            dto.setPlanId(wbPlan.getId());
            extracted(dto);
            WbInform wbInform = new WbInform();
            wbInform.setClientId(wbPlan.getOperaterId());
            wbInform.setClientName(wbPlan.getOperaterName());
            wbInform.setInformType(2L);
            wbInform.setIfRead(2L);
            wbInform.setDelFlag(1L);
            wbInform.setCreateTime(DateUtils.getNowDate());
            wbInform.setTitle(wbPlan.getPlanName());
            SysUser user = SecurityUtils.getLoginUser().getUser();
            wbInform.setCreateBy(user.getUserName());
            wbInform.setContent("你有新的维保任务,预约上门时间是" + new SimpleDateFormat("yyyy-MM-dd").format(wbPlan.getPlanStartDate()));
            iWbInformService.insertWbInform(wbInform);
        }

        return true;
    }


    private void chenDate(WbPlanDto dto) {
        if (ObjectUtils.isEmpty(dto)) {
            throw new GlobalException("计划为空请填写");
        }
        if (dto.getOperaterId().equals(dto.getFireFightingId())) {
            throw new GlobalException("操作者跟消防师不能是同一个人");
        }
        if (dto.getOperaterId().equals(dto.getEngineerId())) {
            throw new GlobalException("操作者跟工程师不能是同一个人");
        }
        if (dto.getFireFightingId().equals(dto.getEngineerId())) {
            throw new GlobalException("消防师跟工程师不能是同一个人");
        }

        if (StringUtils.isEmpty(dto.getPlanType())) {
            throw new GlobalException("计划类型必填");
        }
        //查询维保合同是否在有效期内
        WbContract wbContract = iWbContractService.selectWbContractById(Long.parseLong(dto.getContractId().toString()));
//        Date contractValidityStart = wbContract.getContractValidityStart();
//        Date contractValidityEnd = wbContract.getContractValidityEnd();
//        Date date = new Date();
//        if (date.after(contractValidityEnd)||date.before(contractValidityStart)){
//            throw new GlobalException("合同有效期已过无法创建");
//        }

        Date itemMaintenanceValidityStart = wbContract.getItemMaintenanceValidityStart();
        Date itemMaintenanceValidityEnd = wbContract.getItemMaintenanceValidityEnd();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        LocalDateTime localDateTime = itemMaintenanceValidityEnd.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        // 获取年份和月份
        YearMonth yearMonth = YearMonth.from(localDateTime);
        // 获取该月份的最后一天
        LocalDateTime lastDay = yearMonth.atEndOfMonth().atTime(LocalTime.MAX).withNano(0);

        itemMaintenanceValidityEnd=DateUtils.parseDate(lastDay.format(dateTimeFormatter));

        //判断今天是不是在项目有效期内
        Date date = new Date();
        if (date.before(itemMaintenanceValidityStart)||date.after(itemMaintenanceValidityEnd)){
            throw new RuntimeException("维保项目有效期已过无法创建");
        }


        if (dto.getPlanType().equals(PlanTypeEnums.YEAR.getType())) {
            Date planStartDate = dto.getPlanStartDate();
            Date planEndDate = dto.getPlanEndDate();
            if (planStartDate.before(itemMaintenanceValidityStart) || planEndDate.after(itemMaintenanceValidityEnd)) {
                throw new GlobalException("维保项目有效期已过无法创建");
            }
        } else if (dto.getPlanType().equals(PlanTypeEnums.MONTHLY.getType())) {
            List<String> selectMonths = dto.getSelectMonths();
//            selectMonths.sort(new Comparator<String>() {
//                @Override
//                public int compare(String o1, String o2) {
//                    return o2.compareTo(o1);
//                }
//            });
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            for (String selectMonthDto : selectMonths) {
                String startDate = selectMonthDto + "-01";
                Calendar cld = Calendar.getInstance();
                try {
                    cld.setTime(sdf.parse(startDate));
                } catch (ParseException e) {
                    e.printStackTrace();
                    throw new RuntimeException("新增月检计划失败");
                }
                cld.add(Calendar.MONTH, 1);
                cld.set(Calendar.DAY_OF_MONTH, 0);
                String endDate = sdf.format(cld.getTime());

                Date planStartDate = DateUtils.parseDate(startDate);
                Date planEndDate = DateUtils.parseDate(endDate);
                if (planStartDate.before(itemMaintenanceValidityStart) ||
                        planEndDate.before(itemMaintenanceValidityStart) ||
                        planStartDate.after(itemMaintenanceValidityEnd) ||
                        planEndDate.after(itemMaintenanceValidityEnd)
                ) {
                    throw new GlobalException(selectMonthDto + "月,维保项目有效期已过无法创建");
                }
            }


        }
    }

    /**
     * 修改维保计划
     *
     * @param dto
     * @return
     */
    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public boolean updatePlan(WbPlanDto dto) {
        WbPlan wbPlan = this.selectWbPlanById(dto.getPlanId());

        if (ObjectUtils.isEmpty(wbPlan)) {
            throw new GlobalException("维保计划不存在");
        }


        if (!wbPlan.getExecStatus().equals(PlanExecuteStatusEnums.TO_BEGIN.getStatus())) {
            throw new GlobalException("当前维保不是待开始状态不能修改");
        }
        // 修改维保计划的内容
        BeanUtils.copyProperties(dto, wbPlan);
        wbPlan.setUpdateTime(DateUtils.getNowDate());
        if (!ObjectUtils.isEmpty(dto.getExecStatus()) && dto.getExecStatus().equals(PlanExecuteStatusEnums.COMPLETED.getStatus())) {
            wbPlan.setIfDownload(1L);
        }
        this.updateWbPlan(wbPlan);
        if (!CollectionUtils.isEmpty(dto.getClassifyList())) {
            // 删除掉之前的目录重新做新增
            iWbPlanClassifyService.deleteWbPlanClassifyByPlanId(dto.getPlanId());
            dto.setPlanId(wbPlan.getId());
            this.deleteWbPlanById(wbPlan.getId());
            extracted(dto);
        }
        return true;
    }

    /**
     * 批量删除维保计划
     *
     * @param ids
     * @return
     */
    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public boolean deletePlan(List<Long> ids) {
        for (Long id : ids) {
            WbPlan wbPlan = this.selectWbPlanById(id);
            if (!wbPlan.getExecStatus().equals(PlanExecuteStatusEnums.TO_BEGIN.getStatus())) {
                throw new GlobalException("当前维保不是待开始状态不能删除");
            } else {
                // 同步删除对应的计划目录信息
                //月检
                this.deleteWbPlanById(id);
                iWbPlanClassifyService.deleteWbPlanClassifyByPlanId(id);
                //年检
                wbPlanClassifyYearService.deleteWbPlanClassifyByPlanId(id);

            }


        }
        return true;
    }

    /**
     * 获取维保计划详情
     *
     * @param planId
     * @return
     */
    @Override
    public WbPlanVo getPlanInfo(Long planId) {
        WbPlanVo vo = new WbPlanVo();
        WbPlan wbPlan = selectWbPlanById(planId);
        BeanUtils.copyProperties(wbPlan, vo);
        Optional.ofNullable(iWbContractService.selectWbContractById(vo.getContractId())).ifPresent(c -> vo.setContractName(c.getName()));
        WbPlanClassifyDto dto = new WbPlanClassifyDto();
        dto.setPlanId(planId);
        Optional.ofNullable(iWbPlanClassifyService.getCatalogueItemByPlanId(dto)).ifPresent(vo::setPlanClassifyVos);
        return vo;
    }

    /**
     * 获取维保计划审核记录
     *
     * @param planId
     * @return
     */
    @Override
    public List<WbPlanAuditLogVo> getPlanAuditLog(Long planId) {
        return wbPlanMapper.getPlanAuditLog(planId);
    }

    /**
     * 获取企业维保计划
     *
     * @param userId
     * @return
     */
    @Override
    public List<WbPlan> getEnterprisePlan(WbPlan wbPlan, Long userId) {
        //查询认证企业
        List<WbEntAuth> wbEntAuthList = iWbEntAuthService.selectWbEntAuthListByUserId(userId);
        if (CollectionUtils.isEmpty(wbEntAuthList)) {
            return Collections.emptyList();
        }
        Long authId = wbEntAuthList.get(0).getId();
        WbContract contract = new WbContract();
        contract.setClientId(authId);
        List<WbContract> wbContracts = iWbContractService.selectWbContractList(contract);
        if (CollectionUtils.isEmpty(wbContracts)) {
            return Collections.emptyList();
        }
        List<Long> contractList = wbContracts.stream().map(WbContract::getId).collect(Collectors.toList());
        return wbPlanMapper.getEnterprisePlan(contractList, wbPlan);
    }

    /**
     * 查询当前登录用户审核信息
     *
     * @param execStatus
     * @param userId
     * @return
     */
    @Override
    public List<WbPlan> selectUserAuditPage(Integer execStatus, Long userId) {
        return wbPlanMapper.selectUserAuditPage(execStatus, userId).stream().peek(item -> {
            int count = wbPlanMapper.getPlanAuditLogByPlanId(item.getId(), userId);
            item.setFlag(count != 0);
        }).collect(Collectors.toList());
    }

    /**
     * 统计维保审核数据
     *
     * @param userId
     * @return
     */
    @Override
    public WbPlanVo statisticsMaintenanceAuditNumber(Long userId) {
        return wbPlanMapper.statisticsMaintenanceAuditNumber(userId);
    }

    @Override
    public String previewMonthly(Long planId) {
        if (ObjectUtils.isEmpty(planId)) {
            throw new RuntimeException("计划编号是必传的");
        }
        WbPlan tempWbPlan = wbPlanMapper.selectWbPlanById(planId);
        if (ObjectUtils.isEmpty(tempWbPlan)) {
            throw new RuntimeException("维保计划不存在");
        }
        //合同id
        Long contractId = tempWbPlan.getContractId();
        //维保合同
        WbContract wbContract = wbContractService.selectWbContractById(contractId);
        //业主单位
        WbEntAuth wbEntAuth = wbEntAuthService.selectWbEntAuthById(tempWbPlan.getClientId());


        tempWbPlan.setContractName(wbContract.getCode());

        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(StringUtils.isNotBlank(wbEntAuth.getProvinceString())?wbEntAuth.getProvinceString():"").append(StringUtils.isNotBlank(wbEntAuth.getProvinceString())?"/":"")
                .append(StringUtils.isNotBlank(wbEntAuth.getCityString())?wbEntAuth.getCityString():"").append(StringUtils.isNotBlank(wbEntAuth.getCityString())?"/":"")
                .append(StringUtils.isNotBlank(wbEntAuth.getCountyString())?wbEntAuth.getCountyString():"").append(StringUtils.isNotBlank(wbEntAuth.getCountyString())?"/":"")
                .append(StringUtils.isNotBlank(wbEntAuth.getEntAddress())?wbEntAuth.getEntAddress():"");
        //地址
        tempWbPlan.setClientAddress(stringBuilder.toString());


        WbPlanClassifyDto wbPlanClassifyDto = new WbPlanClassifyDto();
        wbPlanClassifyDto.setPlanId(planId);
        List<WbPlanClassifyVo> list = wbPlanClassifyMapper.getCatalogueItemByPlanId(wbPlanClassifyDto);
        list = list.stream().filter(WbPlanClassifyVo::getIsCheckedStatus).collect(Collectors.toList());
        try {
            String xlsName = XlsCopyToPngUtil.copyXlsMonth(list, tempWbPlan, false);
            return XlsConfig.MONTH_URL + XlsCopyToPngUtil.xlsToPng(xlsName, PlanTypeEnums.MONTHLY.getType());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public String previewYearly(Long planId) {
        if (ObjectUtils.isEmpty(planId)) {
            throw new RuntimeException("计划编号是必传的");
        }
        WbPlan tempWbPlan = wbPlanMapper.selectWbPlanById(planId);
        if (ObjectUtils.isEmpty(tempWbPlan)) {
            throw new RuntimeException("维保计划不存在");
        }

        //合同id
        Long contractId = tempWbPlan.getContractId();
        //维保合同
        WbContract wbContract = wbContractService.selectWbContractById(contractId);
        //业主单位
        WbEntAuth wbEntAuth = wbEntAuthService.selectWbEntAuthById(tempWbPlan.getClientId());


        tempWbPlan.setContractName(wbContract.getCode());

        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(StringUtils.isNotBlank(wbEntAuth.getProvinceString())?wbEntAuth.getProvinceString():"").append(StringUtils.isNotBlank(wbEntAuth.getProvinceString())?"/":"")
                .append(StringUtils.isNotBlank(wbEntAuth.getCityString())?wbEntAuth.getCityString():"").append(StringUtils.isNotBlank(wbEntAuth.getCityString())?"/":"")
                .append(StringUtils.isNotBlank(wbEntAuth.getCountyString())?wbEntAuth.getCountyString():"").append(StringUtils.isNotBlank(wbEntAuth.getCountyString())?"/":"")
                .append(StringUtils.isNotBlank(wbEntAuth.getEntAddress())?wbEntAuth.getEntAddress():"");
        //地址
        tempWbPlan.setClientAddress(stringBuilder.toString());


        List<WbPlanClassifyYearVo> list = wbPlanClassifyYearService.getCatalogueYearItemByPlanId(planId);
        try {
            String xlsName = XlsCopyToPngUtil.copyXlsYear(list, tempWbPlan, false, wbEntAuth);
            return XlsConfig.YEAR_URL + XlsCopyToPngUtil.xlsToPng(xlsName, PlanTypeEnums.YEAR.getType());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 新增个人目录
     *
     * @return
     */
    @Override
    public boolean saveCatalog(List<WbClassifyYearDto> dtoList) {
        dtoList.forEach(item -> {
            WbPlanClassifyYear wbPlanClassifyYear = BeanUtil.copyProperties(item, WbPlanClassifyYear.class, "id");
            wbPlanClassifyYear.setCreateBy(SecurityUtils.getUserId().toString());
            wbPlanClassifyYearService.insertWbPlanClassifyYear(wbPlanClassifyYear);
            List<WbClassifyYearContentVo> wbClassifyYearContentVos = item.getWbClassifyYearContentVos();
            if (CollectionUtils.isEmpty(wbClassifyYearContentVos)) {
                throw new GlobalException("一级目录 《" + item.getClassifyName() + "》 没有子目录,请添加子目录,或者删除该目录");
            }
            wbClassifyYearContentVos.forEach(item2 -> {
                WbPlanClassifyYearContent wbPlanClassifyYearContent = BeanUtil.copyProperties(item2, WbPlanClassifyYearContent.class, "id");
                wbPlanClassifyYearContent.setClassifyYearId(wbPlanClassifyYear.getId());
                wbPlanClassifyYearContentService.insertWbPlanClassifyYearContent(wbPlanClassifyYearContent);
                List<WbClassifyYearContentThreeVo> wbClassifyYearContentThreeVos = item2.getWbClassifyYearContentThreeVos();
                if (CollectionUtils.isEmpty(wbClassifyYearContentThreeVos)) {
                    throw new GlobalException("一级目录《" + item.getClassifyName() + "》 下的二级目录 《" + item2.getClassifyName() + "》 没有子目录,请添加子目录,或者删除该目录");
                }
                wbClassifyYearContentThreeVos.forEach(item3 -> {
                    WbPlanClassifyYearContentThree wbPlanClassifyYearContentThree = BeanUtil.copyProperties(item3, WbPlanClassifyYearContentThree.class, "id");
                    wbPlanClassifyYearContentThree.setClassifyYearContentId(wbPlanClassifyYearContent.getClassifyYearContentId());
                    wbPlanClassifyYearContentThreeService.insertWbPlanClassifyYearContentThree(wbPlanClassifyYearContentThree);
                });

            });
        });
        return true;
    }

    private void extracted(WbPlanDto dto) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        int count = 0;
        Integer i = 0;
        if (dto.getPlanType().equals(PlanTypeEnums.MONTHLY.getType())) {
            //维保计划批量新增集合
            List<WbPlan> wbPlans = new ArrayList<>();
            //二级批量新增集合
            Map<Integer, List<WbPlanClassify>> wbPlanClassifies = new HashMap<>();
            //三级批量新增集合
            List<List<WbClassifyContent>> wbClassifyContentList = new ArrayList<>();
            //三级批量新增集合
            List<WbPlanContent> wbPlanContents = new ArrayList<>();
            List<String> selectMonths = dto.getSelectMonths();
            if (CollectionUtils.isEmpty(selectMonths)) {

                selectMonths.add(DateUtils.parseDateToStr(DateUtils.YYYY_MM, dto.getPlanStartDate()));
            }

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            for (String selectMonthDto : selectMonths) {
                WbPlan wbPlan = BeanUtil.copyProperties(dto, WbPlan.class);
                wbPlan.setPlanName(dto.getClientName() + selectMonthDto + "月度维保计划");
                //获取月份开始和结束日期
                String startDate = selectMonthDto + "-01";
                Calendar cld = Calendar.getInstance();
                try {
                    cld.setTime(sdf.parse(startDate));
                } catch (ParseException e) {
                    e.printStackTrace();
                    throw new RuntimeException("新增月检计划失败");
                }
                cld.add(Calendar.MONTH, 1);
                cld.set(Calendar.DAY_OF_MONTH, 0);
                String endDate = sdf.format(cld.getTime());

                Date date = new Date();
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(date);

                calendar.add(Calendar.DAY_OF_MONTH, 1);

                wbPlan.setPlanStartDate(DateUtils.parseDate(startDate));
                wbPlan.setPlanEndDate(DateUtils.parseDate(endDate));

                wbPlan.setExecStatus(PlanExecuteStatusEnums.TO_BEGIN.getStatus());
                wbPlan.setCreateBy(loginUser.getUserId().toString());
                wbPlan.setCreateTime(DateUtils.getNowDate());
                wbPlan.setUpdateBy(loginUser.getUserId().toString());
                wbPlan.setUpdateTime(DateUtils.getNowDate());
                wbPlans.add(wbPlan);
                for (WbPlanClassifyDto planClassifyDto : dto.getClassifyList()) {
                    // 同步到维保目录
                    WbPlanClassify wbPlanClassify = new WbPlanClassify();
                    BeanUtils.copyProperties(planClassifyDto, wbPlanClassify);
                    wbPlanClassify.setId(null);

                    if (wbPlanClassifies.containsKey(i)) {
                        wbPlanClassifies.get(i).add(wbPlanClassify);
                    } else {
                        List<WbPlanClassify> item = new ArrayList<>();
                        item.add(wbPlanClassify);
                        wbPlanClassifies.put(i, item);
                    }
                    count++;
                    // 同步到维保子目录
                    WbClassifyContent classifyContent = new WbClassifyContent();
                    classifyContent.setClassifyId(planClassifyDto.getId());
                    List<WbClassifyContent> wbClassifyContents = iWbClassifyContentService.selectWbClassifyContentList(classifyContent);
                    if (CollectionUtils.isEmpty(wbClassifyContents)) {
                        throw new GlobalException("第" + count + "条目录没有对应子目录,请为该目录添加子目录");
                    }
                    wbClassifyContentList.add(wbClassifyContents);
                }
                i++;
                count = 0;

                WbInform wbInform = new WbInform();
                wbInform.setClientId(wbPlan.getOperaterId());
                wbInform.setClientName(wbPlan.getOperaterName());
                wbInform.setInformType(2L);
                wbInform.setIfRead(2L);
                wbInform.setDelFlag(1L);
                wbInform.setCreateTime(DateUtils.getNowDate());
                wbInform.setTitle(wbPlan.getPlanName());
                SysUser user = SecurityUtils.getLoginUser().getUser();
                wbInform.setCreateBy(user.getUserName());
                wbInform.setContent("你有新的维保任务,预约上门时间是" + new SimpleDateFormat("yyyy-MM-dd").format(wbPlan.getPlanStartDate()));
                iWbInformService.insertWbInform(wbInform);
            }
            //批量新增一级
            wbPlanMapper.batchSave(wbPlans);
            for (int j = 0; j < wbPlans.size(); j++) {
                List<WbPlanClassify> item = wbPlanClassifies.get(j);
                for (WbPlanClassify wbPlanClassify : item) {
                    wbPlanClassify.setPlanId(wbPlans.get(j).getId());
                    wbPlanClassify.setExecStatus(0L);
                    wbPlanClassify.setDelFlag(0L);
                    wbPlanClassify.setCreateBy(loginUser.getUserId().toString());
                    wbPlanClassify.setCreateTime(DateUtils.getNowDate());
                    wbPlanClassify.setUpdateBy(loginUser.getUserId().toString());
                    wbPlanClassify.setUpdateTime(DateUtils.getNowDate());
                }
            }
            List<WbPlanClassify> collect = wbPlanClassifies.values().stream().flatMap(List::stream)
                    .collect(Collectors.toList());
            //批量新增二级
            wbPlanClassifyMapper.batchSave(collect);
            for (int k = 0; k < collect.size(); k++) {
                List<WbClassifyContent> wbClassifyContents = wbClassifyContentList.get(k);
                for (WbClassifyContent wbClassifyContent : wbClassifyContents) {
                    wbClassifyContent.setClassifyId(collect.get(k).getId());
                    WbPlanContent wbPlanContent = BeanUtil.copyProperties(wbClassifyContent, WbPlanContent.class);
                    wbPlanContent.setDelFlag(1L);
                    wbPlanContent.setCreateBy(loginUser.getUserId().toString());
                    wbPlanContent.setCreateTime(DateUtils.getNowDate());
                    wbPlanContent.setUpdateBy(loginUser.getUserId().toString());
                    wbPlanContent.setUpdateTime(DateUtils.getNowDate());
                    wbPlanContents.add(wbPlanContent);
                }
            }
            //批量新增三级
            wbPlanContentMapper.batchSave(wbPlanContents);
        } else if (dto.getPlanType().equals(PlanTypeEnums.YEAR.getType())) {


            //插入一级二级三级
            List<WbClassifyYearVo> wbClassifyYearVos = wbClassifyYearService.allList(new WbClassifyYear());
            //批量一级
            List<WbPlanClassifyYear> wbPlanClassifyYears = BeanUtil.copyToList(wbClassifyYearVos, WbPlanClassifyYear.class);

            wbPlanClassifyYears.forEach(item -> item.setPlanId(dto.getPlanId()));
            //新增
            wbPlanClassifyYearService.batchAdd(wbPlanClassifyYears);
            //一级map
            Map<Long, WbPlanClassifyYear> wbPlanClassifyYearMap = wbPlanClassifyYears.stream().collect(Collectors.toMap(WbPlanClassifyYear::getId, item -> item));

            //二级vo
            List<WbClassifyYearContentVo> wbClassifyYearContentVoList = new ArrayList<>();
            //装id
            for (int k = 0; k < wbPlanClassifyYears.size(); k++) {
                List<WbClassifyYearContentVo> wbClassifyYearContentVos = wbClassifyYearVos.get(k).getWbClassifyYearContentVos();
                if (CollectionUtils.isEmpty(wbClassifyYearContentVos)) {
                    throw new GlobalException("一级目录 《" + wbPlanClassifyYears.get(k).getClassifyName() + "》 没有子目录,请添加子目录,或者删除该目录");
                }
                for (WbClassifyYearContentVo wbClassifyYearContentVo : wbClassifyYearContentVos) {
                    wbClassifyYearContentVo.setClassifyYearId(wbPlanClassifyYears.get(k).getId());
                    wbClassifyYearContentVoList.add(wbClassifyYearContentVo);
                }

            }
            //批量二级
            List<WbPlanClassifyYearContent> wbPlanClassifyYearContents = BeanUtil.copyToList(wbClassifyYearContentVoList, WbPlanClassifyYearContent.class);
            //新增
            wbPlanClassifyYearContentService.batchAdd(wbPlanClassifyYearContents);

            //三级vo
            List<WbClassifyYearContentThreeVo> wbClassifyYearContentThreeVoList = new ArrayList<>();


            for (int j = 0; j < wbClassifyYearContentVoList.size(); j++) {
                List<WbClassifyYearContentThreeVo> wbClassifyYearContentThreeVos = wbClassifyYearContentVoList.get(j).getWbClassifyYearContentThreeVos();
                if (CollectionUtils.isEmpty(wbClassifyYearContentThreeVos)) {
                    throw new GlobalException("一级目录《" + wbPlanClassifyYearMap.get(wbClassifyYearContentVoList.get(j).getClassifyYearId()).getClassifyName() + "》下的二级目录 《" + wbClassifyYearContentVoList.get(j).getClassifyName() + "》 没有子目录,请添加子目录,或者删除该目录");
                }
                for (WbClassifyYearContentThreeVo wbClassifyYearContentThreeVo : wbClassifyYearContentThreeVos) {
                    wbClassifyYearContentThreeVo.setClassifyYearContentId(wbPlanClassifyYearContents.get(j).getClassifyYearContentId());
                    wbClassifyYearContentThreeVoList.add(wbClassifyYearContentThreeVo);
                }
            }
            //批量三级

            List<WbPlanClassifyYearContentThree> wbPlanClassifyYearContentThrees = BeanUtil.copyToList(wbClassifyYearContentThreeVoList, WbPlanClassifyYearContentThree.class);
            wbPlanClassifyYearContentThreeService.batchAdd(wbPlanClassifyYearContentThrees);
        }

    }


    private List<String> getRole(Long userId) {
        List<Long> roleList = roleMapper.selectRoleListByUserId(userId);
        return roleMapper.getRoleList(roleList);
    }

    @Override
    public List<WbPlan> selectIfDownLoud(WbPlan wbPlan) {
        return wbPlanMapper.selectWbPlanList(wbPlan);
    }

    /**
     * selectUserAuditPageCount
     */
    @Override
    public int selectUserAuditPageCount() {
        Long userId = SecurityUtils.getUserId();
        return wbPlanMapper.selectUserAuditPageCount(userId);

    }


}
